package com.treasure.mall.biz.service.core.order.impl;

import com.treasure.mall.biz.base.AbstractSearchableCrudService;
import com.treasure.mall.biz.base.SpecificationAndSort;
import com.treasure.mall.biz.dto.BaseSaveDTO;
import com.treasure.mall.biz.dto.BaseSearchDTO;
import com.treasure.mall.biz.dto.condition.OrderSearchCondition;
import com.treasure.mall.biz.dto.order.OrderSaveDTO;
import com.treasure.mall.biz.dto.order.OrderUpdateDTO;
import com.treasure.mall.biz.dto.user.ModifyBalanceDTO;
import com.treasure.mall.biz.entity.auction.AuctionBidPO;
import com.treasure.mall.biz.entity.auction.AuctionSessionPO;
import com.treasure.mall.biz.entity.embeddable.GoodsInfo;
import com.treasure.mall.biz.entity.embeddable.ReceivingInfo;
import com.treasure.mall.biz.entity.live.LiveRoomPO;
import com.treasure.mall.biz.entity.order.*;
import com.treasure.mall.biz.entity.product.CategoryPO;
import com.treasure.mall.biz.entity.product.ProductPO;
import com.treasure.mall.biz.entity.user.MerchantPO;
import com.treasure.mall.biz.entity.user.UserPO;
import com.treasure.mall.biz.remote.live.TencentIMService;
import com.treasure.mall.biz.remote.live.dto.PayedSuccessMessageDTO;
import com.treasure.mall.biz.remote.wx.WxTemplateMessageService;
import com.treasure.mall.biz.repository.order.DealOrderRepository;
import com.treasure.mall.biz.repository.order.OrderItemRepository;
import com.treasure.mall.biz.service.core.BaseConfigService;
import com.treasure.mall.biz.service.core.auction.AuctionSessionService;
import com.treasure.mall.biz.service.core.live.LiveRoomService;
import com.treasure.mall.biz.service.core.live.LiveSessionService;
import com.treasure.mall.biz.service.core.order.*;
import com.treasure.mall.biz.service.core.pay.PayService;
import com.treasure.mall.biz.service.core.product.CategoryService;
import com.treasure.mall.biz.service.core.product.ProductService;
import com.treasure.mall.biz.service.core.user.MerchantService;
import com.treasure.mall.biz.service.core.user.UserService;
import com.treasure.mall.zbq.common.Jsr310Utils;
import com.treasure.mall.zbq.common.MathUtils;
import com.treasure.mall.zbq.common.RandomUtils;
import com.treasure.mall.zbq.common.base.ApiResult;
import com.treasure.mall.zbq.common.base.ResultCodeEnum;
import com.treasure.mall.zbq.common.base.TwoTuple;
import com.treasure.mall.zbq.common.exception.ApiException;
import com.treasure.mall.zbq.common.ienum.base.CodeDescEnumHelper;
import com.treasure.mall.zbq.common.ienum.log.AdvanceLogType;
import com.treasure.mall.zbq.common.ienum.order.OrderEnums;
import com.treasure.mall.zbq.common.ienum.product.ProductEnums;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Join;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author allan
 * @version 1.0.0
 * @date 2020/6/11
 */
@Service
@Slf4j
public class DealOrderServiceImpl extends AbstractSearchableCrudService<DealOrderPO, String> implements DealOrderService {
    private DealOrderRepository dealOrderRepository;

    @Autowired
    private UserService userService;
    @Autowired
    private SubOrderLogService orderLogService;
    @Autowired
    private MerchantService merchantService;
    @Autowired
    private BaseConfigService baseConfigService;
    @Autowired
    private ProductService productService;
    @Autowired
    private LiveSessionService liveSessionService;
    @Autowired
    private LiveRoomService liveRoomService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private TencentIMService tencentIMService;
    @Autowired
    private ThreadPoolTaskScheduler taskScheduler;
    @Autowired
    private PayService payService;
    @Autowired
    private AuctionSessionService auctionSessionService;
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    private RebateBillService rebateBillService;
    @Autowired
    private SettlementBillService settlementBillService;
    @Autowired
    private OrderItemRepository orderItemRepository;
    @Autowired
    private WxTemplateMessageService wxTemplateMessageService;
    @Autowired
    private BizOrderService bizOrderService;

    @Value("${zbq.pay.timeout}")
    private long payTimeout;

    @Autowired
    protected DealOrderServiceImpl(DealOrderRepository repository) {
        super(repository);
        this.dealOrderRepository = repository;
    }

    @Override
    protected SpecificationAndSort<DealOrderPO> specificationAndSort(BaseSearchDTO searchDTO) {
        OrderSearchCondition condition = (OrderSearchCondition) searchDTO;
        Specification<DealOrderPO> specification = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            query.distinct(true);
            Join<DealOrderPO, SubOrderPO> join = root.join(DealOrderPO_.subOrderPOS);

            if (condition.getStatus() != -1) {
                OrderEnums.Status status = CodeDescEnumHelper.getEnumTypeByCode(OrderEnums.Status.class, condition.getStatus());
                predicates.add(cb.equal(join.get(SubOrderPO_.status), status));
            }
            if (condition.getPayStatus() != -1) {
                OrderEnums.PayStatus payStatus = CodeDescEnumHelper.getEnumTypeByCode(OrderEnums.PayStatus.class, condition.getPayStatus());
                predicates.add(cb.equal(root.get(DealOrderPO_.payStatus), payStatus));
            }
            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };

        Sort sort = new Sort(Sort.Direction.DESC, "createTime");

        return new SpecificationAndSort<>(specification, sort);
    }


    @Override
    public DealOrderPO create(OrderSaveDTO orderSaveDTO) {
        UserPO userPO = userService.findById(orderSaveDTO.getUserId());

        //账户不足的，全部抵扣完
        if (MathUtils.less(userPO.getBalance(), orderSaveDTO.getDeductBalance())) {
            orderSaveDTO.setDeductBalance(userPO.getBalance());
        }

        DealOrderPO orderPO = new DealOrderPO();
        orderPO.setExtendData(orderSaveDTO.getExtendData());
        orderPO.setOrderId(RandomUtils.randomFlowNo());

        BigDecimal totalGoodsAmount = BigDecimal.ZERO;
        BigDecimal totalIdentifyFee = BigDecimal.ZERO;
        BigDecimal totalFreightAmount = BigDecimal.ZERO;
        BigDecimal totalPmtAmount = BigDecimal.ZERO;
        BigDecimal totalDeductAmount = BigDecimal.ZERO;
        int totalNum = 0;

        Map<Long, List<OrderItemPO>> itemMap = new HashMap<>();
        AuctionBidPO winner = null;
        //准备货品
        for (String product : orderSaveDTO.getProductInfo()) {
            String[] idAndNum = product.split(":");
            long productId = Long.parseLong(idAndNum[0]);
            int num = Integer.parseInt(idAndNum[1]);

            //判断库存
            ProductPO productPO = productService.findById(productId);
            if (productPO.getStatusCode() == 0 || productPO.isDeleted()) {
                throw new ApiException(ApiResult.errorWith(ResultCodeEnum.ILLEGAL_STATE, "商品已下架"));
            }
            if (productPO.availableStore() < num) {
                throw new ApiException(ApiResult.errorWith(ResultCodeEnum.ILLEGAL_STATE, "商品库存不足"));
            }
            //限购判断
            if (productPO.getLimitedNum() > 0) {
                //当前用户该商品购买的总数量
                int buyCount = orderItemRepository.buyCount(userPO.getUserId(), productId, OrderEnums.PayStatus.PAYED);
                //未支付，并且订单为活动中
                int toPayBuyCount = orderItemRepository.buyCountByStatus(userPO.getUserId(), productId, OrderEnums.Status.ACTIVE, OrderEnums.PayStatus.TO_PAY);
                buyCount += toPayBuyCount;
                if (num > productPO.getLimitedNum() - buyCount) {
                    throw new ApiException(ApiResult.errorWith(ResultCodeEnum.ILLEGAL_STATE, "商品已达限购数量"));
                }
            }

            //订单根据商户店铺分类
            List<OrderItemPO> orderItemPOS = itemMap.get(productPO.getMerchantPO().getMerchantId());
            if (orderItemPOS == null || orderItemPOS.isEmpty()) {
                orderItemPOS = new ArrayList<>();
                itemMap.put(productPO.getMerchantPO().getMerchantId(), orderItemPOS);
            }

            OrderItemPO orderItemPO = new OrderItemPO();
            orderItemPO.setGoodsInfo(new GoodsInfo(productPO));
            if (orderSaveDTO.getOrderType() == OrderEnums.OrderType.AUCTION) {
                //如果是拍卖订单，商品金额以出价的最高金额为准，并且保证金要扣除
                AuctionSessionPO sessionPO = auctionSessionService.findById(orderSaveDTO.getAuctionSessionId());
                winner = sessionPO.getWinner();
                orderItemPO.getGoodsInfo().setPrice(winner.getBidAmount());
            }
            orderItemPO.setNum(num);
            orderItemPO.setPmtAmount(BigDecimal.ZERO);
            orderItemPO.setDeductAmount(BigDecimal.ZERO);
            if (orderSaveDTO.isNeedIdentify()) {
                orderItemPO.setIdentifyFee(baseConfigService.getConfig().getBasicsConfig().getIdentityFee());
                orderItemPO.setIdentifyStatus(OrderEnums.IdentifyStatus.TO_IDENTIFY);
            } else {
                orderItemPO.setIdentifyFee(BigDecimal.ZERO);
            }
            orderItemPO.setDeliverStatus(OrderEnums.DeliverStatus.TO_DELIVER);
            orderItemPOS.add(orderItemPO);
        }


        //子订单拆单
        List<SubOrderPO> subOrderPOS = new ArrayList<>();
        for (Map.Entry<Long, List<OrderItemPO>> entry : itemMap.entrySet()) {
            MerchantPO merchantPO = merchantService.findById(entry.getKey());

            SubOrderPO subOrderPO = new SubOrderPO();
            subOrderPO.setSubOrderId(RandomUtils.randomFlowNo());
            subOrderPO.setOrderPO(orderPO);
            subOrderPO.setMerchantPO(merchantPO);

            BigDecimal goodsAmount = BigDecimal.ZERO;
            // TODO: 2020/6/11 运费先不考虑
            BigDecimal freightAmount = BigDecimal.ZERO;
            BigDecimal pmtAmount = BigDecimal.ZERO;
            BigDecimal identifyFee = BigDecimal.ZERO;
            BigDecimal deductAmount = BigDecimal.ZERO;
            int num = 0;

            //货品准备
            for (OrderItemPO orderItemPO : entry.getValue()) {
                // TODO: 2020/6/11 优惠暂时不考虑
                deductAmount = deductAmount.add(orderItemPO.getDeductAmount());
                goodsAmount = goodsAmount.add(orderItemPO.goodsAmount());
                identifyFee = identifyFee.add(orderItemPO.getIdentifyFee());
                orderItemPO.setSubOrderPO(subOrderPO);
                num += orderItemPO.getNum();
            }

            BigDecimal finalAmount = goodsAmount.add(freightAmount).add(identifyFee).subtract(pmtAmount).subtract(deductAmount);
            subOrderPO.setGoodsNum(num);
            subOrderPO.setStatus(OrderEnums.Status.ACTIVE);
            subOrderPO.setFinalAmount(finalAmount);
            subOrderPO.setGoodsAmount(goodsAmount);
            subOrderPO.setFreightAmount(freightAmount);
            subOrderPO.setDeductAmount(deductAmount);
            subOrderPO.setMemo(orderSaveDTO.getUserMemo());
            subOrderPO.setPmtAmount(pmtAmount);
            subOrderPO.setIdentifyFee(identifyFee);
            subOrderPO.setLiveSessionId(orderSaveDTO.getLiveSessionId());
            subOrderPO.setAuctionSessionId(orderSaveDTO.getAuctionSessionId());
            subOrderPO.setOrderItemPOS(entry.getValue());
            subOrderPO.setOrderType(orderSaveDTO.getOrderType());

            subOrderPOS.add(subOrderPO);

            //日志
            orderLogService.log(subOrderPO.getSubOrderId(), OrderEnums.Operation.CREATE, userPO.getUserId(), userPO.getMobile());

            totalFreightAmount = totalFreightAmount.add(freightAmount);
            totalGoodsAmount = totalGoodsAmount.add(goodsAmount);
            totalIdentifyFee = totalIdentifyFee.add(identifyFee);
            totalPmtAmount = totalPmtAmount.add(pmtAmount);
            totalDeductAmount = totalDeductAmount.add(deductAmount);
            totalNum += num;
        }
        //主订单准备
        orderPO.setUserPO(userPO);
//        UserAddressPO addressPO = addressService.findById(orderSaveDTO.getAddressId());
        orderPO.setReceivingInfo(orderSaveDTO.getReceivingInfo());
        orderPO.setGoodsNum(totalNum);
        BigDecimal totalFinalAmount = totalGoodsAmount.add(totalFreightAmount).add(totalIdentifyFee).subtract(totalPmtAmount).subtract(totalDeductAmount);
        BigDecimal surplusAmount = totalFinalAmount;
        if (MathUtils.greater(orderSaveDTO.getDeductBalance(), BigDecimal.ZERO)) {
            surplusAmount = totalFinalAmount.subtract(orderSaveDTO.getDeductBalance());
        }

        orderPO.setFinalAmount(totalFinalAmount);
        orderPO.setDeductAmount(totalDeductAmount);
        orderPO.setGoodsAmount(totalGoodsAmount);
        orderPO.setFreightAmount(totalFreightAmount);
        orderPO.setPmtAmount(totalPmtAmount);
        orderPO.setIdentifyFee(totalIdentifyFee);
        orderPO.setBalance(orderSaveDTO.getDeductBalance());
        //剩余需要支付的金额
        orderPO.setSurplusAmount(surplusAmount);
        orderPO.setPayType(OrderEnums.PayType.WECHAT_PAY);

        orderPO.setPayStatus(OrderEnums.PayStatus.TO_PAY);

        orderPO.setPayExpireTime(LocalDateTime.now().plusMinutes(payTimeout));
        orderPO.setNeedIdentify(orderSaveDTO.isNeedIdentify());

        orderPO.setSubOrderPOS(subOrderPOS);

        if (MathUtils.equalTo(orderPO.getSurplusAmount(), BigDecimal.ZERO)) {
            orderPO.setPayType(OrderEnums.PayType.BALANCE_PAY);
        }
        //创建订单
        orderPO = dealOrderRepository.save(orderPO);

        //如果使用了余额支付，锁定支付部分余额
        if (orderPO.getBalance() != null) {
            userService.modifyLockBalance(userPO.getUserId(), orderPO.getBalance());
        }

        //扣减库存
        for (SubOrderPO subOrderPO : orderPO.getSubOrderPOS()) {
            for (OrderItemPO orderItemPO : subOrderPO.getOrderItemPOS()) {
                ApiResult apiResult = productService.lockStore(orderItemPO.getGoodsInfo().getGoodsId(), orderItemPO.getNum());
                if (!apiResult.isSuccess()) {
                    //扣减失败了，回滚订单
                    delete(orderPO.getOrderId());
                    //释放锁定余额
                    userService.modifyLockBalance(userPO.getUserId(), orderPO.getBalance().negate());
                    throw new ApiException(apiResult);
                }
            }
        }

        return orderPO;
    }

    @Override
    @Transactional
    public void orderPayed(DealOrderPO orderPO) {
        orderPO.setPayStatus(OrderEnums.PayStatus.PAYED);
        orderPO.setPayTime(LocalDateTime.now());

        for (SubOrderPO subOrderPO : orderPO.getSubOrderPOS()) {
            //如果是直播订单和直播间拍卖，增加统计的数量
            if (StringUtils.isNotEmpty(subOrderPO.getLiveSessionId())) {
                liveSessionService.deal(subOrderPO.getLiveSessionId(), orderPO.getFinalAmount());
                // 发送消息
                threadPoolTaskExecutor.execute(() -> tencentIMService.sendPayedSuccess(PayedSuccessMessageDTO.builder()
                        .liveSessionId(subOrderPO.getLiveSessionId())
                        .userId(subOrderPO.getOrderPO().getUserPO().getUserId())
                        .nick(subOrderPO.getOrderPO().getUserPO().getNickName())
                        .validPayOrderSum(subOrderPO.getOrderPO().getUserPO().getValidPayOrderSum())
                        .build()
                ));
            }

            //日志
            orderLogService.log(subOrderPO.getSubOrderId(), OrderEnums.Operation.PAY, orderPO.getUserPO().getUserId(), orderPO.getUserPO().getMobile());

            //返利及货款
            rebate(subOrderPO);

            //给用户增加订单金额
            userService.addOrderAmount(orderPO.getUserPO().getUserId(), orderPO.getFinalAmount());

            //如果是拍卖订单
            if (subOrderPO.getOrderType() == OrderEnums.OrderType.AUCTION) {
                //需要退还保证金
                BizOrderPO bizOrderPO = bizOrderService.findByAuctionAndUser(subOrderPO.getOrderPO().getUserPO().getUserId(), subOrderPO.getAuctionSessionId());
                if (bizOrderPO != null) {
                    bizOrderService.refund(bizOrderPO);
                }
            }

            //发送模板消息
            threadPoolTaskExecutor.execute(() -> wxTemplateMessageService.sendPlaySuccessMessage(subOrderPO));
        }

        //保存订单
        save(orderPO);

    }

    @Override
    public void rebate(SubOrderPO subOrderPO) {
        TwoTuple<UserPO, UserPO> twoTuple = userService.getRebateParents(subOrderPO.getOrderPO().getUserPO().getUserId());
        if (twoTuple == null) {
            return;
        }
        //上级返利用户，可能为空
        UserPO father = twoTuple.first;

        //上上级返利用户，可能为空
        UserPO grant = twoTuple.second;

        //货款
        BigDecimal payment = BigDecimal.ZERO;
        //一级
        BigDecimal fatherRebate = BigDecimal.ZERO;
        //二级
        BigDecimal grantRebate = BigDecimal.ZERO;
        for (OrderItemPO orderItemPO : subOrderPO.getOrderItemPOS()) {
            //如果是直播间的，则取直播间设置的抽佣比例
            if (orderItemPO.getGoodsInfo().getProductType() == ProductEnums.ProductType.LIVE_BROADCAST) {
                LiveRoomPO liveRoomPO = liveRoomService.findById(orderItemPO.getGoodsInfo().getRoomId());
                orderItemPO.getGoodsInfo().setServiceRate(liveRoomPO.getRewardRate());
                //设置直播间商品返利抽成，
                orderItemPO.getGoodsInfo().setRebateRateOne(liveRoomPO.getRebateRateOne());
                orderItemPO.getGoodsInfo().setRebateRateTwo(liveRoomPO.getRebateRateTwo());
            } else {
                //设置店铺的佣金比例
                orderItemPO.getGoodsInfo().setRebateRateOne(subOrderPO.getMerchantPO().getRebateRateOne());
                orderItemPO.getGoodsInfo().setRebateRateTwo(subOrderPO.getMerchantPO().getRebateRateTwo());
            }

            //上级有商户，才需要返利
            if (father != null) {

                //得到返佣比例
                CategoryPO categoryPO = categoryService.getRootCategory(orderItemPO.getGoodsInfo().getCategoryId());
                if (orderItemPO.getGoodsInfo().getRebateRateOne() == null) {
                    orderItemPO.getGoodsInfo().setRebateRateOne(categoryPO.getRebateRateOne());
                }
                if (orderItemPO.getGoodsInfo().getRebateRateTwo() == null) {
                    orderItemPO.getGoodsInfo().setRebateRateTwo(categoryPO.getRebateRateTwo());
                }

                //一级佣金=返利基数*一级佣金比例
                RebateBillPO rebateOne = rebateBillService.create(orderItemPO, father, 0);
                if (rebateOne != null) {
                    orderItemPO.setFatherRebate(rebateOne.getAmount());
                    fatherRebate = fatherRebate.add(rebateOne.getAmount());
                }
                //二级佣金=返利基数*二级佣金比例
                if (grant != null) {
                    RebateBillPO rebateTwo = rebateBillService.create(orderItemPO, grant, 1);
                    orderItemPO.setGrandRebate(rebateTwo.getAmount());
                    grantRebate = grantRebate.add(rebateTwo.getAmount());
                }
            }

            //货款=销售价*数量-返利基数
            SettlementBillPO billPO = settlementBillService.create(orderItemPO);
            if (billPO != null) {
                orderItemPO.setPayment(billPO.getAmount());
                payment = payment.add(billPO.getAmount());
            }
        }


        //一级返利增加带转正金额
        if (MathUtils.greater(fatherRebate, BigDecimal.ZERO)) {
            ModifyBalanceDTO balanceDTO = new ModifyBalanceDTO();
            balanceDTO.setId(father.getUserId());
            balanceDTO.setAmount(fatherRebate);
            balanceDTO.setOrderId(subOrderPO.getSubOrderId());
            balanceDTO.setLogType(AdvanceLogType.LOG_TYPE2);

            userService.modifyBalanceInFuture(balanceDTO);
            //二级返利增加待转正金额
            if (MathUtils.greater(grantRebate, BigDecimal.ZERO)) {
                balanceDTO.setId(grant.getUserId());
                balanceDTO.setAmount(grantRebate);
                userService.modifyBalanceInFuture(balanceDTO);
            }
        }
        //待转正货款增加，给商家
        if (MathUtils.greater(payment, BigDecimal.ZERO)) {
            ModifyBalanceDTO balanceDTO = new ModifyBalanceDTO();
            balanceDTO.setId(subOrderPO.getMerchantPO().getId());
            balanceDTO.setAmount(payment);
            balanceDTO.setOrderId(subOrderPO.getSubOrderId());
            balanceDTO.setLogType(AdvanceLogType.LOG_TYPE9);
            merchantService.modifyBalanceInFuture(balanceDTO);
        }
    }

    @Override
    @Transactional
    public void orderPayed(String orderId) {
        DealOrderPO orderPO = findById(orderId);
        this.orderPayed(orderPO);
    }

    @Override
    public List<DealOrderPO> findUnPayedOrders() {
        Specification<DealOrderPO> specification = (root, query, cb) -> {
            query.distinct(true);
            Join<DealOrderPO, SubOrderPO> join = root.join(DealOrderPO_.subOrderPOS);
            Predicate predicate = cb.equal(join.get(SubOrderPO_.status), OrderEnums.Status.ACTIVE);
            predicate = cb.and(predicate, cb.equal(root.get(DealOrderPO_.payStatus), OrderEnums.PayStatus.TO_PAY));
            predicate = cb.and(predicate, cb.lessThanOrEqualTo(root.get(DealOrderPO_.payExpireTime), LocalDateTime.now()));
            return predicate;
        };

        return dealOrderRepository.findAll(specification);
    }

    @Override
    public void initScheduled() {
        //初始化支付超时订单任务
        List<DealOrderPO> dealOrderPOS = this.findUnPayedOrders();
        for (DealOrderPO orderPO : dealOrderPOS) {
            log.info("支付超时作业加入====订单号：" + orderPO.getOrderId());
            // 在原有的超时时间基础上加上1分钟，避免和API同步执行
            taskScheduler.schedule(() -> payService.payTimeout(orderPO.getOrderId()), Jsr310Utils.DateTime.toDate(orderPO.getPayExpireTime().plusMinutes(1)));
        }
    }

    @Override
    public DealOrderPO updateOrder(OrderUpdateDTO updateDTO) {
        DealOrderPO orderPO = findById(updateDTO.getOrderId());
        orderPO.setExtendData(updateDTO.getExtendData());
        //修改抵扣余额,必须大于0
        if (updateDTO.getDeductBalance() != null && MathUtils.greater(orderPO.getUserPO().getBalance(), BigDecimal.ZERO) && MathUtils.greater(updateDTO.getDeductBalance(), BigDecimal.ZERO)) {
            if (orderPO.getPayStatus() != OrderEnums.PayStatus.TO_PAY) {
                throw new ApiException(ApiResult.errorWith(ResultCodeEnum.ILLEGAL_STATE, "只有待支付的订单可以修改抵扣的余额"));
            }
            if (MathUtils.less(orderPO.getUserPO().getBalance(), updateDTO.getDeductBalance())) {
                updateDTO.setDeductBalance(updateDTO.getDeductBalance());
            }
            orderPO.setBalance(updateDTO.getDeductBalance());
            orderPO.setSurplusAmount(orderPO.getFinalAmount().subtract(orderPO.getBalance()));

            //锁定支付部分余额
            userService.modifyLockBalance(orderPO.getUserPO().getUserId(), orderPO.getBalance());
        }
        if (updateDTO.getReceivingInfo() != null) {
            orderPO.setReceivingInfo(updateDTO.getReceivingInfo());
        }

        return save(orderPO);
    }

    /**
     * 修改订单收货信息
     *
     * @param orderId
     * @param receivingInfo
     */
    @Override
    public void updateOrderShipInfoByOrderId(String orderId, ReceivingInfo receivingInfo) {
        DealOrderPO orderPO = findById(orderId);
        if (receivingInfo != null) {
            orderPO.setReceivingInfo(receivingInfo);
        }
        save(orderPO);
    }


    @Override
    public DealOrderPO save(BaseSaveDTO saveDTO) {
        return null;
    }
}
